
/**
 * Baijiahulian.com Inc. Copyright (c) 2014-2016 All Rights Reserved.
 */

package cn.wenhao.javaClassReload.javaClassElements;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;

import cn.wenhao.javaClassReload.utils.NameRegister;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;

/**
 * @say little Boy, don't be sad.
 * @name Rezar
 * @time Oct 31, 2016
 * @Desc this guy is too lazy, nothing left.
 */
@Slf4j
@Data
public class ObjFieldMemberExecutor implements NameRegister {

    private Object primitiveThat;

    public ObjFieldMemberExecutor() {
    }

    /**
     * 注意,PO 里面的read/write方法里面访问的属性需要是访问当前allFieldMember里面的值 <br/>
     * 
     * 但是:PUTFIELD 就是 putField，如果在字节码里面出现了这个,说明可以直接设置属性值,这个时候不需要转调用read/write方法进行设置属性
     * 
     * bingo
     */
    private Map<Integer, FieldMember> allFieldMember = new HashMap<>();

    public Object invokeField(Integer fieldFlag) {
        FieldMember fieldMember = this.allFieldMember.get(fieldFlag);
        if (fieldMember == null) {
            Object keyObjWithFlagValue = getKeyObjWithFlagValue(fieldFlag);
            throw new IllegalArgumentException("No Such Field: " + keyObjWithFlagValue.toString());
        }
        return fieldMember.getFieldValue();
    }

    /**
     * @param fieldFlag
     * @return
     */
    private Object getKeyObjWithFlagValue(Integer fieldFlag) {
        for (Map.Entry<Object, Integer> flagCache : flagMapper.entrySet()) {
            if (fieldFlag == flagCache.getValue()) {
                return flagCache.getKey();
            }
        }
        return null;
    }

    public void reSetField(Integer fieldFlag, Object fieldValue) {
        this.allFieldMember.get(fieldFlag).setFieldValue(fieldValue);
    }

    /**
     * 添加一个属性的访问器
     * 
     * @param fieldFlag
     * @param fieldMember
     */
    public void addFieldInvoker(Integer fieldFlag, FieldMember fieldMember) {
        this.allFieldMember.put(fieldFlag, fieldMember);
    }

    private AtomicInteger idIncrer = new AtomicInteger(0);
    private Map<Object, Integer> flagMapper = new HashMap<>();

    /**
     * 允许传入属性的名称,方法名称+描述
     */
    @Override
    public Integer register(Object registerObj) {
        Integer flag = flagMapper.get(registerObj);
        if (flag == null) {
            synchronized (registerObj.toString().intern()) {
                if (flagMapper.get(registerObj) == null) {
                    flag = idIncrer.incrementAndGet();
                    flagMapper.put(registerObj, flag);
                }
            }
        }
        log.debug("make flag : {} for registerObj:{} ", flag, registerObj);
        return flag;
    }

    /**
     * @param fm
     */
    public void replaceFieldMember(FieldMember fm) {
        this.allFieldMember.put(this.register(fm.name + fm.descriptor), fm);
    }

}
